/*
* Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.identity.scim.provider.resources;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.jaxrs.designator.PATCH;
import org.wso2.carbon.identity.scim.provider.impl.IdentitySCIMManager;
import org.wso2.carbon.identity.scim.provider.util.JAXRSResponseBuilder;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.charon.core.encoder.Encoder;
import org.wso2.charon.core.exceptions.BadRequestException;
import org.wso2.charon.core.exceptions.CharonException;
import org.wso2.charon.core.exceptions.FormatNotSupportedException;
import org.wso2.charon.core.extensions.UserManager;
import org.wso2.charon.core.protocol.ResponseCodeConstants;
import org.wso2.charon.core.protocol.SCIMResponse;
import org.wso2.charon.core.protocol.endpoints.AbstractResourceEndpoint;
import org.wso2.charon.core.protocol.endpoints.UserResourceEndpoint;
import org.wso2.charon.core.schema.SCIMConstants;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/")
public class UserResource extends AbstractResource {
private static Log logger = LogFactory.getLog(UserResource.class);
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(@PathParam(SCIMConstants.CommonSchemaConstants.ID) String id,
@HeaderParam(SCIMConstants.ACCEPT_HEADER) String format,
@HeaderParam(SCIMConstants.AUTHENTICATION_TYPE_HEADER) String authMechanism,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization) {
Encoder encoder = null;
try {
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
// defaults to application/json.
format = identifyOutputFormat(format);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(format));
// obtain the user store manager
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse scimResponse = userResourceEndpoint.get(id, format, userManager);
// needs to check the code of the response and return 200 0k or other error codes
// appropriately.
return new JAXRSResponseBuilder().buildResponse(scimResponse);
} catch (CharonException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
@POST
public Response createUser(@HeaderParam(SCIMConstants.CONTENT_TYPE_HEADER) String inputFormat,
@HeaderParam(SCIMConstants.ACCEPT_HEADER) String outputFormat,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization,
String resourceString) {
Encoder encoder = null;
try {
// obtain default charon manager
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
// content-type header is compulsory in post request.
if (inputFormat == null) {
String error = SCIMConstants.CONTENT_TYPE_HEADER
+ " not present in the request header";
throw new FormatNotSupportedException(error);
}
// identify input format
inputFormat = identifyInputFormat(inputFormat);
// set the format in which the response should be encoded, if not specified in the
// request,
// defaults to application/json.
outputFormat = identifyOutputFormat(outputFormat);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(outputFormat));
// obtain the user store manager
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse response = userResourceEndpoint.create(resourceString, inputFormat,
outputFormat, userManager);
return new JAXRSResponseBuilder().buildResponse(response);
} catch (CharonException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
@DELETE
@Path("{id}")
public Response deleteUser(@PathParam(SCIMConstants.CommonSchemaConstants.ID) String id,
@HeaderParam(SCIMConstants.ACCEPT_HEADER) String format,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization) {
Encoder encoder = null;
try {
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
// defaults to application/json.
if (format == null) {
format = SCIMConstants.APPLICATION_JSON;
}
// set the format in which the response should be encoded, if not specified in the
// request,
// defaults to application/json.
format = identifyOutputFormat(format);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(format));
// obtain the user store manager
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse scimResponse = userResourceEndpoint.delete(id, userManager, format);
// needs to check the code of the response and return 200 0k or other error codes
// appropriately.
return new JAXRSResponseBuilder().buildResponse(scimResponse);
} catch (CharonException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(@HeaderParam(SCIMConstants.ACCEPT_HEADER) String format,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization,
@QueryParam("attributes") String searchAttribute, @QueryParam("filter") String filter,
@QueryParam("startIndex") String startIndex, @QueryParam("count") String count,
@QueryParam("sortBy") String sortBy, @QueryParam("sortOrder") String sortOrder) {
Encoder encoder = null;
try {
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
// defaults to application/json.
format = identifyOutputFormat(format);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(format));
// obtain the user store manager
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse scimResponse = null;
if (searchAttribute != null) {
scimResponse = userResourceEndpoint.listByAttribute(searchAttribute, userManager,
format);
} else if (filter != null) {
scimResponse = userResourceEndpoint.listByFilter(filter, userManager, format);
} else if (startIndex != null && count != null) {
scimResponse = userResourceEndpoint.listWithPagination(Integer.valueOf(startIndex),
Integer.valueOf(count), userManager, format);
} else if (sortBy != null) {
scimResponse = userResourceEndpoint.listBySort(sortBy, sortOrder, userManager,
format);
} else if (searchAttribute == null && filter == null && startIndex == null
&& count == null && sortBy == null) {
scimResponse = userResourceEndpoint.list(userManager, format);
} else {
// bad request
throw new BadRequestException(ResponseCodeConstants.DESC_BAD_REQUEST_GET);
}
return new JAXRSResponseBuilder().buildResponse(scimResponse);
} catch (CharonException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (BadRequestException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
@PUT
@Path("{id}")
public Response updateUser(@PathParam(SCIMConstants.CommonSchemaConstants.ID) String id,
@HeaderParam(SCIMConstants.CONTENT_TYPE_HEADER) String inputFormat,
@HeaderParam(SCIMConstants.ACCEPT_HEADER) String outputFormat,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization,
String resourceString) {
Encoder encoder = null;
try {
// obtain default charon manager
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
// content-type header is compulsory in post request.
if (inputFormat == null) {
String error = SCIMConstants.CONTENT_TYPE_HEADER
+ " not present in the request header";
throw new FormatNotSupportedException(error);
}
// identify input format
inputFormat = identifyInputFormat(inputFormat);
// set the format in which the response should be encoded, if not specified in the
// request,
// defaults to application/json.
outputFormat = identifyOutputFormat(outputFormat);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(outputFormat));
// obtain the user store manager
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse response = userResourceEndpoint.updateWithPUT(id, resourceString,
inputFormat, outputFormat, userManager);
return new JAXRSResponseBuilder().buildResponse(response);
} catch (CharonException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
@PATCH
@Path("{id}")
public Response updateUserPATCH(@PathParam(SCIMConstants.CommonSchemaConstants.ID) String id,
@HeaderParam(SCIMConstants.CONTENT_TYPE_HEADER) String inputFormat,
@HeaderParam(SCIMConstants.ACCEPT_HEADER) String outputFormat,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization,
String resourceString) {
Encoder encoder = null;
try {
// obtain default charon manager
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
// content-type header is compulsory in post request.
if (StringUtils.isEmpty(inputFormat)) {
String error = SCIMConstants.CONTENT_TYPE_HEADER
+ " not present in the request header";
throw new FormatNotSupportedException(error);
}
// identify input format
inputFormat = identifyInputFormat(inputFormat);
// set the format in which the response should be encoded, if not specified in the
// request,
// defaults to application/json.
outputFormat = identifyOutputFormat(outputFormat);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(outputFormat));
// obtain the user store manager
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse response = userResourceEndpoint.updateWithPATCH(id, resourceString,
inputFormat, outputFormat, userManager);
return new JAXRSResponseBuilder().buildResponse(response);
} catch (CharonException e) {
logger.error("Charon Exception raised while executing PATCH request.", e);
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
logger.error("Request format is not supported.", e);
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
@GET
@Path("/me")
@Produces(MediaType.APPLICATION_JSON)
public Response getAuthorizedUser(
@HeaderParam(SCIMConstants.ACCEPT_HEADER) String format,
@HeaderParam(SCIMConstants.AUTHORIZATION_HEADER) String authorization) {
Encoder encoder = null;
try {
IdentitySCIMManager identitySCIMManager = IdentitySCIMManager.getInstance();
String filter = "userName Eq " + MultitenantUtils.getTenantAwareUsername(authorization);
// defaults to application/json.
format = identifyOutputFormat(format);
// obtain the encoder at this layer in case exceptions needs to be encoded.
encoder = identitySCIMManager.getEncoder(SCIMConstants.identifyFormat(format));
// obtain the user store manager
String SCIM_LIST_USER_PERMISSION = "/permission/admin/login";
UserManager userManager = IdentitySCIMManager.getInstance().getUserManager(
authorization, SCIM_LIST_USER_PERMISSION);
// create charon-SCIM user endpoint and hand-over the request.
UserResourceEndpoint userResourceEndpoint = new UserResourceEndpoint();
SCIMResponse scimResponse = null;
scimResponse = userResourceEndpoint.listByFilter(filter, userManager, format);
return new JAXRSResponseBuilder().buildResponse(scimResponse);
} catch (CharonException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
// create SCIM response with code as the same of exception and message as error message
// of the exception
if (e.getCode() == -1) {
e.setCode(ResponseCodeConstants.CODE_INTERNAL_SERVER_ERROR);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
} catch (FormatNotSupportedException e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
return new JAXRSResponseBuilder().buildResponse(AbstractResourceEndpoint
.encodeSCIMException(encoder, e));
}
}
}